﻿namespace MEF_Test
{
    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Windows;
    using System.Windows.Controls;

    using MEF_Test.Bricks;
    using MEF_Test.Bricks.Mediator;
    using MEF_Test.Contracts;

    using Microsoft.Practices.Unity;

    /// <summary>
    /// The view model responsible for the navigation between the different modules.
    /// </summary>
    public class NavigationPageViewModel : DependencyObject, INotifyPropertyChanged
    {
        // Using a DependencyProperty as the backing store for ModulesList.  This enables animation, styling, binding, etc...

        #region Constants and Fields

        /// <summary>
        /// The Dependency property for the list of the exported modules.
        /// </summary>
        public static readonly DependencyProperty ModulesListProperty = DependencyProperty.Register("ModulesList", typeof(ObservableCollection<IModuleThumbnail>), typeof(NavigationPageViewModel), new UIPropertyMetadata(null));

        /// <summary>
        /// The name of the <see cref="CurrentModuleUri"/> property.
        /// </summary>
        private static readonly string _currentModuleUriPropertyName = PropertyHelper.MemberName<NavigationPageViewModel>(o => o.CurrentModuleUri);

        /// <summary>
        /// The name of the <see cref="CurrentPage"/> property.
        /// </summary>
        private static readonly string _currentPagePropertyName = PropertyHelper.MemberName<NavigationPageViewModel>(o => o.CurrentPage);

        /// <summary>
        /// The backing field for the <see cref="CurrentModuleUri"/> property.
        /// </summary>
        private Uri _currentModuleUri;

        /// <summary>
        /// The backing field for the <see cref="CurrentPage"/> property.
        /// </summary>
        private Page _currentPage;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="NavigationPageViewModel"/> class.
        /// </summary>
        public NavigationPageViewModel()
        {
            // Instead of creating a new CompositionContainer, we *have to* use the one created by the App class,
            // since it is configured to monitor the exports which we want to import in this composition !
            // In order to do so, we'll have to retrieve it from the IoC.
            // Of course, we have to make sure we registered it first hand.
            var container = IoC.Current.Resolve<CompositionContainer>();

            // import the parts.
            container.ComposeParts(this);

            // if a LoadModuleMediation "event" is published, the current module uri will be modified accordingly.
            Mediator<LoadModuleMediation>.Register(a => CurrentModuleUri = a.ModuleUri);
        }

        #endregion

        #region Events

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the URI of the current module.
        /// </summary>
        /// <value>The URI of the current module.</value>
        public Uri CurrentModuleUri
        {
            get
            {
                return _currentModuleUri;
            }

            set
            {
                if (_currentModuleUri != value)
                {
                    _currentModuleUri = value;
                    PropertyChanged(this, new PropertyChangedEventArgs(_currentModuleUriPropertyName));
                }
            }
        }

        /// <summary>
        /// Gets or sets the current page.
        /// </summary>
        /// <value>The current page.</value>
        public Page CurrentPage
        {
            get
            {
                return _currentPage;
            }

            set
            {
                if (_currentPage != null)
                {
                    _currentPage = value;
                    PropertyChanged(this, new PropertyChangedEventArgs(_currentPagePropertyName));
                }
            }
        }

        /// <summary>
        /// Gets or sets the list of the exported modules.
        /// </summary>
        /// <value>The modules list.</value>
        /// <remarks>This is just a .net wrapper around a dependency property. Use <see cref="ModulesListProperty"/>.</remarks>
        [ImportMany(typeof(IModuleThumbnail))]
        public ObservableCollection<IModuleThumbnail> ModulesList
        {
            get { return (ObservableCollection<IModuleThumbnail>)GetValue(ModulesListProperty); }
            set { SetValue(ModulesListProperty, value); }
        }

        #endregion
    }
}
